package com.cn.redis.service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;


public class BaseRedisService<K, V>{
	@Autowired
	private RedisTemplate<K, V> redisTemplate;
	/**
	 * add value
	 * 
	 * @param key
	 * @param value
	 * @param expire
	 * @return
	 */
	public boolean set(final K key, final V value, final long expire) {
		boolean result = redisTemplate.execute(new RedisCallback<Boolean>() {
			public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
				RedisSerializer<K> serializer = getKeySerializer();
				byte[] k = serializer.serialize(key);
				try {
					byte[] v = getValueSerializer().serialize(value);
					System.out.println(getValueSerializer().getClass());
					if (v != null) {
						connection.set(k, v);
						connection.expire(k, expire);
						return true;
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
				return false;
			}
		});
		return result;
	}

	public int mSet(final Map<K, V> data, final long expire) {
		if (data == null) {
			return 0;
		}
		int result = redisTemplate.execute(new RedisCallback<Integer>() {
			@Override
			public Integer doInRedis(RedisConnection connection) throws DataAccessException {
				int inc = 0;
				RedisSerializer<K> serializer = getKeySerializer();
				Map<byte[], byte[]> map = new HashMap<byte[], byte[]>();
				for (K k : data.keySet()) {
					V v = data.get(k);
					byte[] kbt = serializer.serialize(k);
					byte[] vbt = getValueSerializer().serialize(v);
					if (vbt != null) {
						connection.set(kbt, vbt);
						connection.expire(kbt, expire);
						++inc;
					}
				}
				return inc;
			}
		});
		return result;
	}

	/**
	 * get value
	 * 
	 * @param key
	 * @return
	 */
	public V get(final K key) {
		V v = redisTemplate.execute(new RedisCallback<V>() {
			public V doInRedis(RedisConnection connection) throws DataAccessException {
				RedisSerializer<K> serializer = getKeySerializer();
				byte[] k = serializer.serialize(key);
				byte[] value = connection.get(k);
				return getValueSerializer().deserialize(value);
			}

		});
		return v;
	}

	/**
	 * key in()
	 * 
	 * @param keys
	 * @return
	 */
	public List<V> mGet(final K[] keys) {
		List<V> values = redisTemplate.execute(new RedisCallback<List<V>>() {
			@Override
			public List<V> doInRedis(RedisConnection connection) throws DataAccessException {
				RedisSerializer<K> serializer = getKeySerializer();
				List<byte[]> bytes = new ArrayList<byte[]>();
				List<V> result = new ArrayList<V>();
				for (K key : keys) {
					byte[] k = serializer.serialize(key);
					bytes.add(k);
				}
				int size = bytes.size();

				byte[][] keyArray = new byte[size][];

				for (int i = 0; i < keyArray.length; i++) {
					keyArray[i] = bytes.get(i);
				}
				List<byte[]> temp = connection.mGet(keyArray);
				for (byte[] bt : temp) {
					V v = getValueSerializer().deserialize(bt);
					if (v != null) {
						result.add(v);
					}
				}
				return result;

			}
		});
		return values;
	}
	
	public boolean delete(K k){
		try {
			redisTemplate.delete(k);
			return true;
		} catch (Exception e) {
			return false;
		}
	}
	
	/*
	 * 
	 */
	
	public RedisTemplate<K, V> getRedisTemplate() {
		return redisTemplate;
	}

	public void setRedisTemplate(RedisTemplate<K, V> redisTemplate) {
		this.redisTemplate = redisTemplate;
	}
	
	public RedisSerializer<K> getKeySerializer(){
		return (RedisSerializer<K>) redisTemplate.getKeySerializer();
	}
	
	public RedisSerializer<V> getValueSerializer(){
		return (RedisSerializer<V>) redisTemplate.getValueSerializer();
	}
}